package com.hopes.bizz.close.gis.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.hopes.bizz.close.basic.dto.ClosedRoadDTO;
import com.hopes.bizz.close.basic.entity.ClosedAccessControlEntity;
import com.hopes.bizz.close.basic.entity.ClosedControlAreaEntity;
import com.hopes.bizz.close.basic.entity.ClosedGateEntity;
import com.hopes.bizz.close.basic.entity.ClosedRoadEntity;
import com.hopes.bizz.close.basic.service.ClosedAccessControlService;
import com.hopes.bizz.close.basic.service.ClosedControlAreaService;
import com.hopes.bizz.close.basic.service.ClosedGateService;
import com.hopes.bizz.close.basic.service.ClosedRoadService;
import com.hopes.bizz.close.common.constant.CloseModuleEnums;
import com.hopes.bizz.close.gis.dto.AccessRecordDTO;
import com.hopes.bizz.close.gis.dto.GateRecordDTO;
import com.hopes.bizz.close.gis.service.ClosedLayerService;
import com.hopes.bizz.close.gis.vo.ClosedRoadVO;
import com.hopes.bizz.close.gis.vo.GateAccessLayerVO;
import com.hopes.bizz.close.gis.vo.GateRecordVO;
import com.hopes.bizz.close.gis.vo.HazardCarLayerVO;
import com.hopes.bizz.close.hazard.entity.ClosedAlarmHazardCarEntity;
import com.hopes.bizz.close.hazard.service.ClosedAlarmHazardCarService;
import com.hopes.bizz.close.visitor.entity.ClosedGeneralCarRecordEntity;
import com.hopes.bizz.close.visitor.entity.ClosedHazardCarApplyEntity;
import com.hopes.bizz.close.visitor.entity.ClosedHazardCarRecordEntity;
import com.hopes.bizz.close.visitor.entity.ClosedPersonRecordEntity;
import com.hopes.bizz.close.visitor.service.ClosedGeneralCarRecordService;
import com.hopes.bizz.close.visitor.service.ClosedHazardCarApplyService;
import com.hopes.bizz.close.visitor.service.ClosedHazardCarRecordService;
import com.hopes.bizz.close.visitor.service.ClosedPersonRecordService;
import com.hopes.bizz.close.visitor.vo.ClosedHazardCarApplyVO;
import com.hopes.bizz.close.visitor.vo.ClosedPersonRecordVO;
import com.hopes.bizz.common.core.constant.CommonConstant;
import com.hopes.bizz.common.core.util.DateUtils;
import com.hopes.boss.common.core.constant.CommonConstants;
import com.hopes.boss.common.entity.BaseEntity;
import com.hopes.boss.common.security.util.SecurityUtils;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @author yumr
 * @ProjectName bizz
 * @Description 图层数据服务
 * @time 2024/2/23 9:43
 */
@Service
@RequiredArgsConstructor
public class ClosedLayerServiceImpl implements ClosedLayerService {

    private final ClosedGateService closedGateService;
    private final ClosedRoadService closedRoadService;
    private final ClosedControlAreaService closedControlAreaService;
    private final ClosedAccessControlService closedAccessControlService;
    private final ClosedHazardCarApplyService closedHazardCarApplyService;
    private final ClosedAlarmHazardCarService closedAlarmHazardCarService;

    private final ClosedPersonRecordService closedPersonRecordService;
    private final ClosedHazardCarRecordService closedHazardCarRecordService;
    private final ClosedGeneralCarRecordService closedGeneralCarRecordService;

    @Override
    public HazardCarLayerVO queryHazardCarInfo(Long applyId) {
        final ClosedHazardCarApplyVO hazardCarApplyVO = closedHazardCarApplyService.getVoById(applyId);
        if (ObjUtil.isNull(hazardCarApplyVO)) {
            return new HazardCarLayerVO();
        }
        final List<ClosedAlarmHazardCarEntity> closedAlarmHazardCarList = closedAlarmHazardCarService.list(
                Wrappers.<ClosedAlarmHazardCarEntity>lambdaQuery()
                        .eq(ClosedAlarmHazardCarEntity::getLicencePlateNumber, hazardCarApplyVO.getLicencePlateNum())
                        .orderByDesc(ClosedAlarmHazardCarEntity::getAlarmTime));
        return new HazardCarLayerVO(hazardCarApplyVO, closedAlarmHazardCarList);
    }

    @Override
    public List<GateAccessLayerVO> queryGateAccessByType(CloseModuleEnums.ParkCompanyTypeEnum parkCompanyTypeEnum) {
        final List<ClosedGateEntity> gateList = closedGateService.list(
                Wrappers.<ClosedGateEntity>lambdaQuery().eq(ClosedGateEntity::getGateType, parkCompanyTypeEnum.name()));
        final List<ClosedAccessControlEntity> accessControlList = closedAccessControlService.list(
                Wrappers.<ClosedAccessControlEntity>lambdaQuery().eq(ClosedAccessControlEntity::getAccessType, parkCompanyTypeEnum.name()).orderByAsc(ClosedAccessControlEntity::getOrgId));
        final List<GateAccessLayerVO> resList = gateList.stream().map(e -> new GateAccessLayerVO(CloseModuleEnums.GateAccessTypeEnum.gate.name(), e)).collect(Collectors.toList());
        resList.addAll(accessControlList.stream().map(e -> new GateAccessLayerVO(CloseModuleEnums.GateAccessTypeEnum.access.name(), e)).collect(Collectors.toList()));
        return resList;
    }

    @Override
    public List<GateRecordVO> queryLayerGateRecord(GateRecordDTO gateRecordDTO) {
        final Long gateId = gateRecordDTO.getGateId();
        final List<ClosedHazardCarRecordEntity> hazardCarRecordList = closedHazardCarRecordService.list(
                Wrappers.<ClosedHazardCarRecordEntity>lambdaQuery().eq(ClosedHazardCarRecordEntity::getGateId, gateId).orderByDesc(ClosedHazardCarRecordEntity::getInOutTime));
        final List<ClosedGeneralCarRecordEntity> generalCarRecordList = closedGeneralCarRecordService.list(
                Wrappers.<ClosedGeneralCarRecordEntity>lambdaQuery().eq(ClosedGeneralCarRecordEntity::getGateId, gateId).orderByDesc(ClosedGeneralCarRecordEntity::getInOutTime));
        final List<GateRecordVO> resList = hazardCarRecordList.stream().map(GateRecordVO::new).collect(Collectors.toList());
        resList.addAll(generalCarRecordList.stream().map(GateRecordVO::new).collect(Collectors.toList()));
        Collections.sort(resList);
        return resList;
    }

    @Override
    public List<ClosedPersonRecordVO> queryLayerAccessRecord(AccessRecordDTO accessRecordDTO) {
        final List<ClosedPersonRecordEntity> closedPersonRecordList = closedPersonRecordService.list(
                Wrappers.<ClosedPersonRecordEntity>lambdaQuery().eq(ClosedPersonRecordEntity::getAccessId, accessRecordDTO.getAccessId())
                        .ge(ClosedPersonRecordEntity::getInOutTime, accessRecordDTO.getStartTime()).le(ClosedPersonRecordEntity::getInOutTime, accessRecordDTO.getEndTime())
                        .orderByDesc(ClosedPersonRecordEntity::getInOutTime));
        return closedPersonRecordList.stream().map(e -> {
            final ClosedPersonRecordVO recordVO = new ClosedPersonRecordVO();
            BeanUtils.copyProperties(e, recordVO);
            return recordVO;
        }).collect(Collectors.toList());
    }

    @Override
    public List<ClosedControlAreaEntity> queryLayerControlArea() {
        final LambdaQueryWrapper<ClosedControlAreaEntity> wrapper = Wrappers.lambdaQuery();
        wrapper.eq(SecurityUtils.isCompany(), ClosedControlAreaEntity::getOrgId, SecurityUtils.getOrgId());
        return closedControlAreaService.list(wrapper);
    }

    @Override
    public List<ClosedRoadVO> queryLayerRoad(ClosedRoadDTO closedRoadDTO) {
        final LambdaQueryWrapper<ClosedRoadEntity> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.eq(StrUtil.isNotBlank(closedRoadDTO.getRoadType()), ClosedRoadEntity::getRoadType, closedRoadDTO.getRoadType());
        final List<ClosedRoadEntity> list = closedRoadService.list(queryWrapper);
        if (CollUtil.isEmpty(list)) {
            return new ArrayList<>();
        }
        return list.stream().map(e -> {
            final ClosedRoadVO roadVO = new ClosedRoadVO();
            BeanUtils.copyProperties(e, roadVO);
            roadVO.setAllowPass(calcIsAllowPass(e.getPeriodStart(), e.getPeriodEnd()));
            return roadVO;
        }).collect(Collectors.toList());
    }

    private String calcIsAllowPass(String periodStart, String periodEnd) {
        final Date time = Calendar.getInstance().getTime();
        if (StrUtil.isBlank(periodStart) || StrUtil.isBlank(periodEnd)) {
            return CommonConstant.boolean_true_string;
        }
        final String nowDate = DateUtils.limitDay(time);
        final Date periodEndDate = DateUtils.parseDate(nowDate + " " + periodEnd, DateUtils.FORMAT_SECOND);
        final Date periodStartDate = DateUtils.parseDate(nowDate + " " + periodStart, DateUtils.FORMAT_SECOND);
        return time.after(periodStartDate) && time.before(periodEndDate) ? CommonConstant.boolean_true_string : CommonConstant.boolean_false_string;
    }
}
